package com.gitee.l0km.casban.utils;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.gitee.l0km.aocache.annotations.AoWeakCacheable;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

public class CollectionUtils {

	private CollectionUtils() {
	}

	public static <T,C extends Collection<T>> C toNonullCollection(Iterable<T> input,C collection, Function<T, T> transform){
		checkNotNull(input,"input is null");
		FluentIterable.from(input)
			.filter(Predicates.notNull())
			.transform(transform == null ? Functions.<T>identity():transform)
			.copyInto(collection);
		return collection;
	}

	@SafeVarargs
	public static <T,C extends Collection<T>> C toNonullCollection(Function<T, T> transform,C collection,T... input){
		checkNotNull(input,"input is null");
		return toNonullCollection(FluentIterable.from(input),collection,transform);
	}

	public static <T> LinkedHashSet<T> toNonullLinkedHashSet(Iterable<T> input, Function<T, T> transform){
		return toNonullCollection(input,new LinkedHashSet<T>(), transform);
	}

	@SafeVarargs
	public static <T> LinkedHashSet<T> toNonullLinkedHashSet(Function<T, T> transform,T...input){
		return toNonullCollection(transform, new LinkedHashSet<T>(), input);
	}

	/**
	 * 将给定的列表转换为不可变列表。
	 * 如果输入列表为空，则返回空的不可变列表；
	 * 如果输入列表已经是不可变列表，则直接返回；
	 * 否则创建一个新的不可变列表副本。
	 * 
	 * @param <T>  列表元素类型
	 * @param list 需要转换的源列表
	 * @return 不可变列表
	 * @since 1.5.0
	 */
	public static <T> List<T> asImmutableList(List<T> list) {
		if (null == list) {
			return ImmutableList.of();
		}
		if(list instanceof ImmutableList) {
			return (ImmutableList<T>)list;
		}
		return ImmutableList.copyOf(list);
	}
	/**
	 * 将给定的集合转换为不可变集合。
	 * 如果输入集合为空，则返回空的不可变集合；
	 * 如果输入集合已经是不可变集合，则直接返回；
	 * 否则创建一个新的不可变集合副本。
	 * 
	 * @param <T> 集合元素类型
	 * @param set 需要转换的源集合
	 * @return 不可变集合
	 * @since 1.5.0
	 */
	public static <T> Set<T> asImmutableSet(Set<T> set) {
		if(null == set) {
			return ImmutableSet.of();
		}
		if(set instanceof ImmutableSet) {
			return (ImmutableSet<T>)set;
		}
		return ImmutableSet.copyOf(set);
	}

	/**
	 * 将给定的Map转换为不可变Map。
	 * 如果输入Map为空，则返回空的不可变Map；
	 * 如果输入Map已经是不可变Map，则直接返回；
	 * 否则创建一个新的不可变Map副本。
	 * 
	 * @param <K> Map键类型
	 * @param <V> Map值类型
	 * @param map 需要转换的源Map
	 * @return 不可变Map
	 * @since 1.5.0
	 */
	@AoWeakCacheable(maximumSize = 200, expireAfterAccess = 20, expireAfterAccessTimeUnit = TimeUnit.SECONDS)
	public static <K, V> Map<K, V> asImmutableMap(Map<K, V> map) {
		if (null == map) {
			return ImmutableMap.of();
		}
		if(map instanceof ImmutableMap) {
			return (ImmutableMap<K,V>)map;
		}
		return ImmutableMap.copyOf(map);
	}
}
